package org.piggy.core.utils;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import org.apache.commons.lang3.StringUtils;
import org.piggy.common.config.ServiceDefinition;
import org.piggy.common.constants.BasicConst;
import org.piggy.common.rule.Rule;
import org.piggy.core.context.GatewayContext;
import org.piggy.core.manager.DynamicConfigManager;
import org.piggy.core.request.GatewayRequest;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;


public class RequestUtil {

	public static GatewayContext routeGatewayContext(FullHttpRequest request, ChannelHandlerContext channelHandlerContext) {

		GatewayRequest gateWayRequest = doGatewayRequest(request, channelHandlerContext);

//		Rule rule = getRule(gateWayRequest.getPath());
		Rule rule = getRulePro(gateWayRequest.getPath());
		if(rule == null){
			return null;
		}

		ServiceDefinition serviceDefinition = DynamicConfigManager.getInstance().getServiceDefinition(rule.getServiceName());
		if(serviceDefinition == null){
			return null;
		}

		return new GatewayContext(
				serviceDefinition.getProtocol(),
				channelHandlerContext,
				HttpUtil.isKeepAlive(request),
				gateWayRequest,
				rule);
	}

	private static GatewayRequest doGatewayRequest(FullHttpRequest fullHttpRequest, ChannelHandlerContext channelHandlerContext) {
		HttpHeaders headers = fullHttpRequest.headers();
		String host = headers.get(HttpHeaderNames.HOST);
		HttpMethod method = fullHttpRequest.method();
		String uri = fullHttpRequest.uri();
		String clientIp = getClientIp(channelHandlerContext, fullHttpRequest);
		String contentType = HttpUtil.getMimeType(fullHttpRequest) == null ? null : HttpUtil.getMimeType(fullHttpRequest).toString();
		Charset charset = HttpUtil.getCharset(fullHttpRequest, StandardCharsets.UTF_8);

		return new GatewayRequest(
				charset,
				clientIp,
				host,
				uri,
				method,
				contentType,
				headers,
				fullHttpRequest);
	}
	
	/**
	 * 获取客户端ip
	 */
	private static String getClientIp(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) {
		String xForwardedValue = fullHttpRequest.headers().get(BasicConst.HTTP_FORWARD_SEPARATOR);
		
		String clientIp = null;
		if(StringUtils.isNotEmpty(xForwardedValue)) {
			List<String> values = Arrays.asList(xForwardedValue.split(", "));
			if(values.size() >= 1 && StringUtils.isNotBlank(values.get(0))) {
				clientIp = values.get(0);
			}
		}
		if(clientIp == null) {
			InetSocketAddress inetSocketAddress = (InetSocketAddress)channelHandlerContext.channel().remoteAddress();
			clientIp = inetSocketAddress.getAddress().getHostAddress();
		}
		return clientIp;
	}

	private static Rule getRule(String path) {
		return DynamicConfigManager.getInstance().getRule(path);
	}

	private static Rule getRulePro(String path) {
		return DynamicConfigManager.getInstance().getRulePro(path);
	}
}
